home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 January / PCWorld_2003-01_cd.bin / Software / Vyzkuste / rychlokurz / httrack.exe / {app} / src / htsname.c < prev    next >
C/C++ Source or Header  |  2002-11-17  |  44KB  |  1,268 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       savename routine (compute output filename)             */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htsname.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htstools.h"
  43. #include "htsmd5.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <ctype.h>
  47. /* END specific definitions */
  48.  
  49. #undef test_flush
  50. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  51.  
  52. #define ADD_STANDARD_PATH \
  53.     {  /* ajout nom */\
  54.       char buff[HTS_URLMAXSIZE*2];\
  55.       buff[0]='\0';\
  56.       strncatbuff(buff,start_pos,(int) (nom_pos - start_pos));\
  57.       url_savename_addstr(save,buff);\
  58.     }
  59.  
  60. #define ADD_STANDARD_NAME(shortname) \
  61.     {  /* ajout nom */\
  62.       char buff[HTS_URLMAXSIZE*2];\
  63.       standard_name(buff,dot_pos,nom_pos,fil_complete,(shortname));\
  64.       url_savename_addstr(save,buff);\
  65.     }
  66.  
  67.  
  68. /* Avoid stupid DOS system folders/file such as 'nul' */
  69. /* Based on linux/fs/umsdos/mangle.c */
  70. static const char *hts_tbdev[] =
  71. {
  72.     "/prn", "/con", "/aux", "/nul",
  73.     "/lpt1", "/lpt2", "/lpt3", "/lpt4",
  74.     "/com1", "/com2", "/com3", "/com4",
  75.     "/clock$",
  76.     "/emmxxxx0", "/xmsxxxx0", "/setverxx",
  77.     ""
  78. };
  79.  
  80.  
  81.  
  82. // forme le nom du fichier α sauver (save) α partir de fil et adr
  83. // systΦme intelligent, qui renomme en cas de besoin (exemple: deux INDEX.HTML et index.html)
  84. int url_savename(char* adr_complete,char* fil_complete,char* save,char* former_adr,char* former_fil,char* referer_adr,char* referer_fil,httrackp* opt,lien_url** liens,int lien_tot,lien_back* back,int back_max,cache_back* cache,hash_struct* hash,int ptr,int numero_passe) {
  85.   char newfil[HTS_URLMAXSIZE*2];   /* ="" */
  86.   char* fil;
  87.   char* adr;
  88.   char* print_adr;
  89.   char *start_pos=NULL,*nom_pos=NULL,*dot_pos=NULL;  // Position nom et point
  90.   // pour changement d'extension ou de nom (content-disposition)
  91.   int ext_chg=0;
  92.   char ext[256];
  93.   int max_char=0;
  94.   //CLEAR
  95.   newfil[0]=ext[0]='\0';
  96.  
  97.   /* 8-3 ? */
  98.   switch(opt->savename_83) {
  99.   case 1:
  100.     max_char=8;
  101.     break;
  102.   case 2:
  103.     max_char=30;
  104.     break;
  105.   default:
  106.     max_char=8;
  107.     break;
  108.   }
  109.  
  110.   // effacer save
  111.   save[0]='\0';
  112.   // fil
  113.   fil = fil_complete;
  114.   // et adr (sauter user/pass)
  115.   // on prend le parti de mettre les fichiers avec login/pass au mΩme endroit que si ils
  116.   // Θtaient capturΘs sans ces paramΦtres
  117.   // c'est pour cette raison qu'on ignore totalement adr_complete (mΩme pour la recherche en table de hachage)
  118.   adr=jump_identification(adr_complete);
  119.  
  120.   // α afficher sans ftp://
  121.   print_adr=jump_protocol(adr);
  122.  
  123.   // court-circuit pour lien primaire
  124.   if (strnotempty(adr)==0) {
  125.     if (strcmp(fil,"primary")==0) {
  126.       strcatbuff(save,"primary.html");
  127.       return 0;
  128.     }
  129.   }
  130.  
  131.  
  132.   // vΘrifier que le nom n'a pas dΘja ΘtΘ calculΘ (si oui le renvoyer tel que)
  133.   // vΘrifier que le nom n'est pas dΘja pris...
  134.   // NOTE: si on cherche /toto/ et que /toto est trouvΘ on le prend (et rΘciproquqment) ** // **
  135.   if (liens!=NULL) { 
  136.     int i;
  137.  
  138. #if HTS_HASH
  139.     i=hash_read(hash,adr,fil_complete,1);      // recherche table 1 (adr+fil)
  140.     if (i>=0) {    // ok, trouvΘ
  141.       strcpybuff(save,liens[i]->sav);
  142.       return 0;
  143.     }
  144.     i=hash_read(hash,adr,fil_complete,2);      // recherche table 2 (former_adr+former_fil)
  145.     if (i>=0) {    // ok, trouvΘ
  146.       // copier location moved!
  147.       strcpybuff(adr_complete,liens[i]->adr);
  148.       strcpybuff(fil_complete,liens[i]->fil);
  149.       // et save
  150.       strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  151.       return 0;
  152.     }
  153. #else
  154.     for(i=lien_tot-1;i>=0;i--) {        
  155. #if HTS_CASSE
  156.       if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  157. #else
  158.       if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  159. #endif
  160.       {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  161.         strcpybuff(save,liens[i]->sav);
  162.         return 0;
  163.       }
  164.       if (liens[i]->former_adr) {     // tester ancienne loc?
  165. #if HTS_CASSE
  166.         if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete)==0))
  167. #else
  168.         if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete)))
  169. #endif
  170.         {
  171.           // copier location moved!
  172.           strcpybuff(adr_complete,liens[i]->adr);
  173.           strcpybuff(fil_complete,liens[i]->fil);
  174.           // et save
  175.           strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  176.           return 0;
  177.         }
  178.       }
  179.     }
  180. #endif
  181.  
  182.     // chercher sans / ou avec / dans former
  183.     {
  184.       char fil_complete_patche[HTS_URLMAXSIZE*2];
  185.       strcpybuff(fil_complete_patche,fil_complete);
  186.       // Version avec ou sans /
  187.       if (fil_complete_patche[strlen(fil_complete_patche)-1]=='/')
  188.         fil_complete_patche[strlen(fil_complete_patche)-1]='\0';
  189.       else
  190.         strcatbuff(fil_complete_patche,"/");
  191. #if HTS_HASH
  192.       i=hash_read(hash,adr,fil_complete_patche,2);      // recherche table 2 (former_adr+former_fil)
  193.       if (i>=0) {
  194.         // Θcraser fil et adr (pas former_fil?????)
  195.         strcpybuff(adr_complete,liens[i]->adr);
  196.         strcpybuff(fil_complete,liens[i]->fil);
  197.         // Θcrire save
  198.         strcpybuff(save,liens[i]->sav);
  199.         return 0;
  200.       }
  201. #else
  202.       // mΩme boucle en gros
  203.       for(i=lien_tot-1;i>=0;i--) {        
  204.         if (liens[i]->former_adr) {    // former-adr?
  205. #if HTS_CASSE
  206.           if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete_patche)==0))
  207. #else
  208.           if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete_patche)))
  209. #endif
  210.           {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  211.             // Θcraser fil et adr (pas former_fil?????)
  212.             strcpybuff(adr_complete,liens[i]->adr);
  213.             strcpybuff(fil_complete,liens[i]->fil);
  214.             // Θcrire save
  215.             strcpybuff(save,liens[i]->sav);
  216.             return 0;
  217.           }
  218.         }
  219.       }
  220. #endif
  221.     }
  222.   }
  223.  
  224.   // vΘrifier la non prΘsence de paramΦtres dans le nom de fichier
  225.   // si il y en a, les supprimer (ex: truc.cgi?subj=aspirateur)
  226.   // nΘanmoins, gardΘ pour vΘrifier la non duplication (voir aprΦs)
  227.   {
  228.     char* a;
  229.     a=strchr(fil,'?');
  230.     if (a!=NULL) {
  231.       strncatbuff(newfil,fil,(int) (a - fil));
  232.     } else {
  233.       strcpybuff(newfil,fil);
  234.     }
  235.     fil=newfil;
  236.   }
  237.   // dΘcoder %
  238.   strcpybuff(fil,unescape_http(fil));
  239.   /*
  240.   {
  241.     char tempo[HTS_URLMAXSIZE*2];
  242.     int i,j=0;
  243.     for (i=0;i<(int) strlen(fil);i++) {
  244.       if (fil[i]=='%') {
  245.         i++;
  246.         tempo[j++]=(char) ehex(fil+i);
  247.         i++;    // sauter 2 caractΦres finalement
  248.       } else
  249.         tempo[j++]=fil[i];
  250.     }
  251.     tempo[j++]='\0';
  252.     strcpybuff(fil,tempo);
  253.   }
  254.   */
  255.   
  256.   
  257.   /* replace shtml to html.. */
  258.   switch (ishtml(fil)) {       /* .html,.shtml,.. */
  259.   case 1:
  260.     if ( 
  261.       (strcmp(get_ext(fil),"html") != 0)
  262.       && (strcmp(get_ext(fil),"htm") != 0)
  263.       ) {
  264.       strcpybuff(ext,"html");
  265.       ext_chg=1;
  266.     }
  267.     break;
  268.     case 0:
  269.       if (!strnotempty(ext)) {
  270.         if (is_userknowntype(get_ext(fil))) {      // mime known by user
  271.           char mime[1024];
  272.           mime[0]=ext[0]='\0';
  273.           get_userhttptype(0,mime,get_ext(fil));
  274.           if (strnotempty(mime)) {
  275.             give_mimext(ext,mime);
  276.             if (strnotempty(ext)) {
  277.               ext_chg=1;
  278.             }
  279.           }
  280.         }
  281.       }
  282.       break;
  283.   }
  284.   
  285.  
  286.   // si option check_type activΘe
  287.   if ((opt->check_type) && (!ext_chg)) {
  288.     int ishtest;
  289.     if ( (!strfield(adr_complete,"file://")) 
  290.       && (!strfield(adr_complete,"ftp://")) 
  291.       ) {
  292.       // tester type avec requΦte HEAD si on ne connait pas le type du fichier
  293.       if (!(   (opt->check_type==1) && (fil[strlen(fil)-1]=='/')   ))    // slash doit Ωtre html?
  294.       if ((ishtest=ishtml(fil)) < 0) { // on ne sait pas si c'est un html ou un fichier..
  295.         // lire dans le cache
  296.         htsblk r = cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  297.         if (r.statuscode != -1) {  // pas d'erreur de lecture cache
  298.           char s[16]; s[0]='\0';
  299.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  300.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type (from cache) %s%s"LF,adr_complete,fil_complete);
  301.             test_flush;
  302.           }
  303.           if (strnotempty(r.cdispo)) {        /* filename given */
  304.             ext_chg=2;      /* change filename */
  305.             strcpybuff(ext,r.cdispo);
  306.           }
  307.           else if (!may_unknown(r.contenttype) || ishtest == -2) {  // on peut patcher α priori?
  308.             give_mimext(s,r.contenttype);  // obtenir extension
  309.             if (strnotempty(s)>0) {        // on a reconnu l'extension
  310.               ext_chg=1;
  311.               strcpybuff(ext,s);
  312.             }
  313.           }
  314.           //
  315.         } else {          // test imposible dans le cache, faire une requΩte
  316.           //
  317. #if HTS_ANALYSTE
  318.           int hihp=_hts_in_html_parsing;
  319. #endif
  320.           int has_been_moved=0;
  321.           char curr_adr[HTS_URLMAXSIZE*2],curr_fil[HTS_URLMAXSIZE*2];
  322.           curr_adr[0]=curr_fil[0]='\0';
  323. #if HTS_ANALYSTE
  324.           _hts_in_html_parsing=2;  // test
  325. #endif
  326.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  327.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type %s%s"LF,adr_complete,fil_complete);
  328.             test_flush;
  329.           }
  330.           strcpybuff(curr_adr,adr_complete);
  331.           strcpybuff(curr_fil,fil_complete);
  332.           // ajouter dans le backing le fichier en mode test
  333.           // savename: rien car en mode test
  334.           if (back_add(back,back_max,opt,cache,curr_adr,curr_fil,BACK_ADD_TEST,referer_adr,referer_fil,1,NULL)!=-1) {
  335.             int b;
  336.             b=back_index(back,back_max,curr_adr,curr_fil,BACK_ADD_TEST);         
  337.             if (b>=0) {
  338.               int petits_tours=0;
  339.               int get_test_request=0;       // en cas de bouclage sur soi mΩme avec HEAD, tester avec GET.. parfois c'est la cause des problΦmes
  340.               do {
  341.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  342.                 if (back[b].status>0) back_wait(back,back_max,opt,cache,0);        
  343.                 if (ptr>=0)
  344.                   back_fillmax(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  345.   
  346.                 // on est obligΘ d'appeler le shell pour le refresh..
  347. #if HTS_ANALYSTE
  348.                 {
  349.                   
  350.                   // Transfer rate
  351.                   engine_stats();
  352.                   
  353.                   // Refresh various stats
  354.                   HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  355.                   HTS_STAT.stat_errors=fspc(NULL,"error");
  356.                   HTS_STAT.stat_warnings=fspc(NULL,"warning");
  357.                   HTS_STAT.stat_infos=fspc(NULL,"info");
  358.                   HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  359.                   HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  360.  
  361.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  362.                     return -1;
  363.                   } else if (_hts_cancel) {    // cancel 2 ou 1 (cancel parsing)
  364.                     back_delete(back,b);       // cancel test
  365.                   }
  366.                 }
  367. #endif
  368.                 
  369.                 
  370.                 // traitement des 304,303..
  371.                 if (back[b].status<=0) {
  372.                   if (    (back[b].r.statuscode==301)
  373.                        || (back[b].r.statuscode==302)
  374.                        || (back[b].r.statuscode==303)
  375.                        || (back[b].r.statuscode==307)
  376.                      ) {    // agh moved.. un tit tour de plus
  377.                     if ((petits_tours<5) && (former_adr) && (former_fil)) { // on va pas tourner en rond non plus!
  378.                       if ((int) strnotempty(back[b].r.location)) {    // location existe!
  379.                         char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  380.                         mov_url[0]=mov_adr[0]=mov_fil[0]='\0';
  381.                         //
  382.                         strcpybuff(mov_url,back[b].r.location);    // copier URL
  383.                         if (ident_url_relatif(mov_url,curr_adr,curr_fil,mov_adr,mov_fil)>=0) {                        
  384.                           // si non bouclage sur soi mΩme, ou si test avec GET non testΘ
  385.                           if ((strcmp(mov_adr,curr_adr)) || (strcmp(mov_fil,curr_fil)) || (get_test_request==0)) {
  386.                             // bouclage?
  387.                             if ((!strcmp(mov_adr,curr_adr)) && (!strcmp(mov_fil,curr_fil)))
  388.                               get_test_request=1;     // faire requΦte avec GET
  389.  
  390.                             // recopier former_adr/fil?
  391.                             if ((former_adr) && (former_fil)) {
  392.                               if (strnotempty(former_adr)==0) {    // Pas dΘja notΘ
  393.                                 strcpybuff(former_adr,curr_adr);
  394.                                 strcpybuff(former_fil,curr_fil);
  395.                               }
  396.                             }
  397.  
  398.                             // check explicit forbidden - don't follow 3xx in this case
  399.                             {
  400.                               int set_prio_to=0;
  401.                               robots_wizard* robots = (robots_wizard*) opt->robotsptr;
  402.                               if (hts_acceptlink(opt,ptr,lien_tot,liens,
  403.                                 mov_adr,mov_fil,
  404.                                 opt->filters.filters,opt->filters.filptr,opt->maxfilter,
  405.                                 robots,
  406.                                 &set_prio_to,
  407.                                 NULL) == 1) 
  408.                               {  /* forbidden */
  409.                                 has_been_moved = 1;
  410.                                 back_delete(back,b);    // ok
  411.                                 strcpybuff(curr_adr,mov_adr);
  412.                                 strcpybuff(curr_fil,mov_fil);
  413.                                 mov_url[0]='\0';
  414.                               }
  415.                             }
  416.                             
  417.                             // ftp: stop!
  418.                             if (strfield(mov_url,"ftp://")) {    // ftp, ok on arrΩte
  419.                               has_been_moved = 1;
  420.                               back_delete(back,b);    // ok
  421.                               strcpybuff(curr_adr,mov_adr);
  422.                               strcpybuff(curr_fil,mov_fil);
  423.                             } else if (*mov_url) {
  424.                               char* methode;
  425.                               if (!get_test_request)
  426.                                 methode=BACK_ADD_TEST;      // tester avec HEAD
  427.                               else {
  428.                                 methode=BACK_ADD_TEST2;     // tester avec GET
  429.                                 if ( opt->errlog!=NULL ) {
  430.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Loop with HEAD request (during prefetch) at %s%s"LF,curr_adr,curr_fil);
  431.                                   test_flush;
  432.                                 }                    
  433.                               }
  434.                               // Ajouter
  435.                               if (back_add(back,back_max,opt,cache,mov_adr,mov_fil,methode,referer_adr,referer_fil,1,NULL)!=-1) {    // OK
  436.                                 if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  437.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"(during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  438.                                   test_flush;
  439.                                 }
  440.                                 
  441.                                 // libΘrer emplacement backing actuel et attendre le prochain
  442.                                 back_delete(back,b);
  443.                                 strcpybuff(curr_adr,mov_adr);
  444.                                 strcpybuff(curr_fil,mov_fil);
  445.                                 b=back_index(back,back_max,curr_adr,curr_fil,methode);         
  446.                                 if (!get_test_request)
  447.                                   has_been_moved = 1;       // sinon ne pas forcer has_been_moved car non dΘplacΘ
  448.                                 petits_tours++;
  449.                                 //
  450.                               } else {// sinon on fait rien et on s'en va.. (ftp etc)
  451.                                 if ( (opt->debug>1)  && (opt->errlog)) {
  452.                                   fspc(opt->errlog,"debug"); fprintf(opt->errlog,"Warning: Savename redirect backing error at %s%s"LF,mov_adr,mov_fil);
  453.                                   test_flush;
  454.                                 } 
  455.                               }
  456.                             }
  457.                           } else {
  458.                             if ( opt->errlog!=NULL ) {
  459.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop to same filename)"LF,adr_complete,fil_complete);
  460.                               test_flush;
  461.                             }
  462.                           }
  463.                           
  464.                         }
  465.                       }
  466.                     } else{  // arrΩter les frais
  467.                       if ( opt->errlog!=NULL ) {
  468.                         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop)"LF,adr_complete,fil_complete);
  469.                         test_flush;
  470.                       }
  471.                     }
  472.                   }  // ok, leaving
  473.                 }
  474.                 
  475.               } while(back[b].status>0);
  476.               
  477.               // Si non dΘplacΘ, forcer type?
  478.               if (!has_been_moved) {
  479.                 if (back[b].r.statuscode!=-10) {    // erreur
  480.                   if (strnotempty(back[b].r.contenttype)==0)
  481.                     strcpybuff(back[b].r.contenttype,"text/html");    // message d'erreur en html
  482.                   // Finalement on, renvoie un erreur, pour ne toucher α rien dans le code
  483.                   // libΘrer emplacement backing
  484.                   /*if (opt->errlog!=NULL) {
  485.                     fspc(opt->errlog,0); fprintf(opt->errlog,"Error: (during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  486.                     test_flush;
  487.                   }                    
  488.                   back_delete(back,b);
  489.                   return -1;        // ERREUR (404 par exemple)
  490.                   */
  491.                 } 
  492.                 
  493.                 {            // pas d'erreur, changer type?
  494.                   char s[16];
  495.                   s[0]='\0';
  496.                   if (strnotempty(back[b].r.cdispo)) {        /* filename given */
  497.                     ext_chg=2;      /* change filename */
  498.                     strcpybuff(ext,back[b].r.cdispo);
  499.                   }
  500.                   else if (!may_unknown(back[b].r.contenttype) || ishtest == -2 ) {  // on peut patcher α priori? (pas interdit ou pas de type)
  501.                     give_mimext(s,back[b].r.contenttype);  // obtenir extension
  502.                     if (strnotempty(s)>0) {    // on a reconnu l'extension
  503.                       ext_chg=1;
  504.                       strcpybuff(ext,s);
  505.                     }
  506.                   }
  507.                 }
  508.               }
  509.               // FIN Si non dΘplacΘ, forcer type?
  510.  
  511.               // libΘrer emplacement backing
  512.               back_delete(back,b);
  513.               
  514.               // --- --- ---
  515.               // oops, a ΘtΘ dΘplacΘ.. on recalcule en rΘcursif (osons!)
  516.               if (has_been_moved) {
  517.                 // copier adr, fil (optionnel, mais sinon marche pas pour le rip)
  518.                 strcpybuff(adr_complete,curr_adr);
  519.                 strcpybuff(fil_complete,curr_fil);
  520.                 // copier adr, fil
  521.                 
  522.                 return url_savename(curr_adr,curr_fil,save,NULL,NULL,referer_adr,referer_fil,opt,liens,lien_tot,back,back_max,cache,hash,ptr,numero_passe);
  523.               }
  524.               // --- --- ---
  525.               
  526.             }
  527.             
  528.           } else {
  529.             printf("PANIC! : Savename Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  530. #if BDEBUG==1
  531.             printf("error while savename crash adding\n");
  532. #endif
  533.             if (opt->errlog) {
  534.               fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unexpected savename backing error at %s%s"LF,adr,fil_complete);
  535.               test_flush;
  536.             } 
  537.             
  538.           }
  539.           // restaurer
  540. #if HTS_ANALYSTE
  541.           _hts_in_html_parsing=hihp;
  542. #endif
  543.         }  // cachΘ?
  544.       }
  545.     }
  546.   }
  547.  
  548.  
  549.  
  550.   // - - - DEBUT NOMMAGE - - -
  551.  
  552.   // Donner nom par dΘfaut?
  553.   if (fil[strlen(fil)-1]=='/')  {
  554.     if (!strfield(adr_complete,"ftp://"))
  555.       strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut!!
  556.     else {
  557.       if (!opt->proxy.active)
  558.         strcatbuff(fil,DEFAULT_FTP);     // nommer page par dΘfaut (texte)
  559.       else
  560.         strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut (α priori ici html depuis un proxy http)
  561.     }
  562.   }
  563.   // Changer extension?
  564.   // par exemple, php3 sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  565.   if (ext_chg) {  // changer ext
  566.     char* a=fil+strlen(fil)-1;
  567.     if ( (opt->debug>1) && (opt->log!=NULL) ) {
  568.       fspc(opt->log,"debug");
  569.       if (ext_chg==1)
  570.         fprintf(opt->log,"Changing link extension %s%s to .%s"LF,adr_complete,fil_complete,ext);
  571.       else
  572.         fprintf(opt->log,"Changing link name %s%s to %s"LF,adr_complete,fil_complete,ext);
  573.       test_flush;
  574.     }
  575.     if (ext_chg==1) {
  576.       while((a > fil) && (*a!='.') && (*a!='/')) a--;
  577.       if (*a=='.') *a='\0';  // couper
  578.       strcatbuff(fil,".");      // recopier point
  579.     } else {
  580.       while(( a > fil) && (*a!='/')) a--;
  581.       if (*a=='/') a++;
  582.       *a='\0';
  583.    }
  584.     strcatbuff(fil,ext);    // copier ext/nom
  585.   }
  586.  
  587.   // Rechercher premier / et dernier .
  588.   {  
  589.     char* a=fil+strlen(fil)-1;
  590.  
  591.     // passer structures
  592.     start_pos=fil;
  593.     while(( a > fil) && (*a != '/') && (*a != '\\')) {
  594.       if (*a == '.')    // point? noter position
  595.         if (!dot_pos)
  596.           dot_pos=a;
  597.         a--;
  598.     }
  599.     if ((*a=='/') || (*a=='\\')) a++;
  600.     nom_pos = a;
  601.   }
  602.  
  603.   
  604.   // un nom de fichier est gΘnΘrΘ
  605.   // s'il existe dΘja, alors on le mofifie lΘgΦrement
  606.  
  607.   // ajouter nom du site Θventuellement en premier
  608.   if (opt->savename_type == -1) {    // utiliser savename_userdef! (%h%p/%n%q.%t)
  609.     char* a = opt->savename_userdef;
  610.     char* b = save;
  611.     /*char *nom_pos=NULL,*dot_pos=NULL;  // Position nom et point */
  612.     char tok;
  613.  
  614.     /*
  615.     {  // Rechercher premier /
  616.       char* a=fil+strlen(fil)-1;
  617.       // passer structures
  618.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  619.         if (*a == '.')    // point? noter position
  620.         if (!dot_pos)
  621.           dot_pos=a;
  622.         a--;
  623.       }
  624.       if ((*a=='/') || (*a=='\\')) a++;
  625.       nom_pos = a;
  626.     }
  627.     */
  628.  
  629.     // Construire nom
  630.     while ((*a) && (((int) (b - save)) < HTS_URLMAXSIZE ) ) {    // parser, et pas trop long..
  631.       if (*a == '%') {
  632.         int short_ver=0;
  633.         a++;
  634.         if (*a == 's') {
  635.           short_ver=1;
  636.           a++;
  637.         }
  638.         *b='\0';
  639.         switch(tok=*a++) {
  640.           case '[':            // %[param]
  641.             if (strchr(a,']')) {
  642.               char name[256];
  643.               char* c=name;
  644.               while(*a!=']') {
  645.                 *c++=*a++;
  646.               }
  647.               a++;
  648.               *c++='\0';
  649.               strcatbuff(name,"=");           /* param=.. */
  650.               c=strchr(fil_complete,'?');
  651.               /* parameters exists */
  652.               if (c) {
  653.                 c=strstr(c,name);     /* finds param= */
  654.                 if (c) {
  655.                   c+=strlen(name);    /* jumps "param=" */
  656.                   while( (*c) && (*c!='&'))
  657.                     *b++=*c++;
  658.                 }
  659.               }
  660.             }
  661.           break;
  662.           case '%': *b++='%'; break;
  663.           case 'n':    // nom sans ext
  664.             if (dot_pos) {
  665.               if (!short_ver)    // Noms longs
  666.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  667.               else
  668.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  669.             } else {
  670.               if (!short_ver)    // Noms longs
  671.                 strcpybuff(b,nom_pos);
  672.               else
  673.                 strncatbuff(b,nom_pos,8);
  674.             }
  675.             b+=strlen(b);   // pointer α la fin
  676.             break;
  677.           case 'N':    // nom avec ext
  678.             // RECOPIE NOM + EXT
  679.             *b='\0';
  680.             if (dot_pos) {
  681.               if (!short_ver)    // Noms longs
  682.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  683.               else
  684.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  685.             } else {
  686.               if (!short_ver)    // Noms longs
  687.                 strcpybuff(b,nom_pos);
  688.               else
  689.                 strncatbuff(b,nom_pos,8);
  690.             }
  691.             b+=strlen(b);   // pointer α la fin
  692.             // RECOPIE NOM + EXT
  693.             *b='\0';
  694.             if (dot_pos) {
  695.               if (!short_ver)    // Noms longs
  696.                 strcpybuff(b,dot_pos+1);
  697.               else
  698.                 strncatbuff(b,dot_pos+1,3);
  699.             } else {
  700.               if (!short_ver)    // Noms longs
  701.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  702.               else
  703.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  704.             }
  705.             b+=strlen(b);   // pointer α la fin
  706.             //
  707.             break;
  708.           case 't':    // ext
  709.             *b='\0';
  710.             if (dot_pos) {
  711.               if (!short_ver)    // Noms longs
  712.                 strcpybuff(b,dot_pos+1);
  713.               else
  714.                 strncatbuff(b,dot_pos+1,3);
  715.             } else {
  716.               if (!short_ver)    // Noms longs
  717.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  718.               else
  719.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  720.             }
  721.             b+=strlen(b);   // pointer α la fin
  722.             break;
  723.           case 'p':    // path sans dernier /
  724.             *b='\0';
  725.             if (nom_pos != fil + 1) { // pas: /index.html (chemin nul)
  726.               if (!short_ver) {   // Noms longs
  727.                 strncatbuff(b,fil,(int) (nom_pos - fil) - 1);
  728.               } else {
  729.                 char pth[HTS_URLMAXSIZE*2],n83[HTS_URLMAXSIZE*2];
  730.                 pth[0]=n83[0]='\0';
  731.                 //
  732.                 strncatbuff(pth,fil,(int) (nom_pos - fil) - 1);
  733.                 long_to_83(opt->savename_83,n83,pth);
  734.                 strcpybuff(b,n83);
  735.               }
  736.             }
  737.             b+=strlen(b);   // pointer α la fin
  738.             break;
  739.           case 'h':    // host
  740.             *b='\0';
  741.             if (strcmp(adr_complete,"file://")==0) {
  742.               if (!short_ver)    // Noms longs
  743.                 strcpybuff(b,"localhost");
  744.               else
  745.                 strcpybuff(b,"local");
  746.             } else {
  747.               if (!short_ver)    // Noms longs
  748.                 strcpybuff(b,print_adr);
  749.               else
  750.                 strncatbuff(b,print_adr,8);
  751.             }
  752.             b+=strlen(b);   // pointer α la fin
  753.             break;
  754.           case 'M':         /* host/address?query MD5 (128-bits) */
  755.             *b='\0';
  756.             {
  757.               char digest[32+2];
  758.               char buff[HTS_URLMAXSIZE*2];
  759.               digest[0]=buff[0]='\0';
  760.               strcpybuff(buff,adr);
  761.               strcatbuff(buff,fil_complete);
  762.               domd5mem(buff,strlen(buff),digest,1);
  763.               strcpybuff(b,digest);
  764.             }
  765.             b+=strlen(b);   // pointer α la fin
  766.             break;
  767.           case 'Q': case 'q':         /* query MD5 (128-bits/16-bits) 
  768.                                          GENERATED ONLY IF query string exists! */
  769.             *b='\0';
  770.             strncatbuff(b,url_md5(fil_complete),(tok == 'Q')?32:4);
  771.             b+=strlen(b);   // pointer α la fin
  772.             break;
  773.         }
  774.       } else
  775.         *b++=*a++;
  776.     }
  777.     *b++='\0';
  778.     //
  779.     // Types prΘdΘfinis
  780.     //
  781.  
  782.   } 
  783.   //
  784.   // Structure originale
  785.   else if (opt->savename_type%100==0) { 
  786.     /* recopier www.. */
  787.     if (opt->savename_type!=100) {  
  788.       if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  789.         if (strcmp(adr_complete,"file://")==0) {
  790.           //## if (*adr==lOCAL_CHAR) {
  791.           if (opt->savename_83 != 1)  // noms longs
  792.             strcatbuff(save,"localhost");
  793.           else
  794.             strcatbuff(save,"local");
  795.         } else {
  796.           // adresse url
  797.           if (!opt->savename_83) {  // noms longs (et pas de .)
  798.             strcatbuff(save,print_adr);
  799.           } else {  // noms 8-3
  800.             if (strlen(print_adr)>4) {
  801.               if (strfield(print_adr,"www."))
  802.                 strncatbuff(save,print_adr+4,max_char);
  803.               else
  804.                 strncatbuff(save,print_adr,8);
  805.             } else strncatbuff(save,print_adr,max_char);
  806.           }
  807.         }
  808.         if (*fil!='/') strcatbuff(save,"/");
  809.       }
  810.     }
  811.   
  812. #if HTS_CASSE==0
  813.     hts_lowcase(save);
  814. #endif  
  815.         
  816.     /*
  817.     // ne sert α rien car a dΘja ΘtΘ filtrΘ normalement
  818.     if ((*fil=='.') && (*(fil+1)=='/'))          // ./index.html ** //
  819.       url_savename_addstr(save,fil+2);
  820.     else                                               // index.html ou /index.html
  821.       url_savename_addstr(save,fil);
  822.     if (save[strlen(save)-1]=='/') 
  823.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  824. */
  825.  
  826.     /* add name */
  827.     ADD_STANDARD_PATH;
  828.     ADD_STANDARD_NAME(0);
  829.  
  830.   }
  831.   //
  832.   // Structure html/image
  833.   else {    
  834.     // dossier "web" ou "www.xxx" ?
  835.     if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  836.       if ((opt->savename_type/100)%2) {
  837.         if (strcmp(adr_complete,"file://")==0) {
  838.         //## if (*adr==lOCAL_CHAR) {
  839.           if (opt->savename_83 != 1)  // noms longs
  840.             strcatbuff(save,"localhost/");
  841.           else
  842.             strcatbuff(save,"local/");
  843.         } else {
  844.           // adresse url
  845.           if (!opt->savename_83) {  // noms longs
  846.             strcatbuff(save,print_adr); strcatbuff(save,"/");
  847.           } else {  // noms 8-3
  848.             if (strlen(print_adr)>4) {
  849.               if (strfield(print_adr,"www."))
  850.                 strncatbuff(save,print_adr+4,max_char);
  851.               else
  852.                 strncatbuff(save,print_adr,max_char);
  853.               strcatbuff(save,"/");
  854.             } else { 
  855.               strncatbuff(save,print_adr,max_char); strcatbuff(save,"/");
  856.             }
  857.           }
  858.         }
  859.       } else {
  860.         strcatbuff(save,"web/");    // rΘpertoire gΘnΘral
  861.       }
  862.     } 
  863.  
  864.     // si un html α coup s√r
  865.     if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  866.       if (opt->savename_type%100==2) {  // html/
  867.         strcatbuff(save,"html/");
  868.       }
  869.     } else {
  870.       if ((opt->savename_type%100==1) || (opt->savename_type%100==2)) {  // html & images
  871.         strcatbuff(save,"images/");
  872.       }
  873.     }
  874.     
  875.     switch (opt->savename_type%100) {
  876.     case 4: case 5: {           // sΘparer par types
  877.       char* a=fil+strlen(fil)-1;
  878.       // passer structures
  879.       while(( a > fil) && (*a != '/') && (*a != '\\')) a--;      
  880.       if ((*a=='/') || (*a=='\\')) a++;
  881.  
  882.       // html?
  883.       if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  884.         if (opt->savename_type%100==5)
  885.           strcatbuff(save,"html/");
  886.       } else {
  887.         char* a=fil+strlen(fil)-1;
  888.         while(( a> fil) && (*a != '/') && (*a != '.')) a--;      
  889.         if (*a!='.')
  890.           strcatbuff(save,"other");
  891.         else
  892.           strcatbuff(save,a+1);
  893.         strcatbuff(save,"/");
  894.       }
  895.       /*strcatbuff(save,a);*/
  896.       /* add name */
  897.       ADD_STANDARD_NAME(0);
  898.             }
  899.       break;
  900.     case 99: {                  // 'codΘ' .. c'est un gadget
  901.       int i;
  902.       int j;
  903.       char* a;
  904.       char C[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  905.       int L;
  906.       // pseudo-CRC sur fil et adr pour initialiser gΘnΘrateur alΘatoire..
  907.       unsigned int s=0;
  908.       L=strlen(C);
  909.       for(i=0;i<(int) strlen(fil_complete);i++) {
  910.         s+=(unsigned int) fil_complete[i];
  911.       }
  912.       for(i=0;i<(int) strlen(adr_complete);i++) {
  913.         s+=(unsigned int) adr_complete[i];
  914.       }
  915.       srand(s);
  916.       
  917.       j=strlen(save);
  918.       for(i=0;i<8;i++) {
  919.         char c=C[(rand()%L)];
  920.         save[i+j]=c;
  921.       }
  922.       save[i+j]='\0';
  923.       // ajouter extension
  924.       a=fil+strlen(fil)-1;
  925.       while(( a > fil) && (*a != '/') && (*a != '.')) a--;
  926.       if (*a=='.') {
  927.         strcatbuff(save,a);    // ajouter
  928.       }
  929.              } 
  930.       break;
  931.     default: {   // noms sans les noms des rΘpertoires
  932.       // ne garder que le nom, pas la structure
  933.       /*
  934.       char* a=fil+strlen(fil)-1;
  935.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  936.       if ((*a=='/') || (*a=='\\')) a++;
  937.       strcatbuff(save,a);
  938.       */
  939.  
  940.       /* add name */
  941.       ADD_STANDARD_NAME(0);
  942.             }
  943.       break;
  944.     }
  945.  
  946. #if HTS_CASSE==0
  947.     hts_lowcase(save);
  948. #endif  
  949.  
  950.     if (save[strlen(save)-1]=='/') 
  951.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  952.   }
  953.  
  954.  
  955.   // vΘrifier qu'on ne doit pas forcer l'extension
  956.   // par exemple, asp sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  957.   /*if (ext_chg) {
  958.     char* a=save+strlen(save)-1;
  959.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  960.     if (*a=='.') *a='\0';  // couper
  961.     // recopier extension
  962.     strcatbuff(save,".");
  963.     strcatbuff(save,ext);    // copier ext
  964.   }*/
  965.   // de mΩme en cas de manque d'extension on en place une de maniΦre forcΘe..
  966.   // cela Θvite les /chez/toto et les /chez/toto/index.html incompatibles
  967.   if (opt->savename_type != -1) {
  968.     char* a=save+strlen(save)-1;
  969.     while(( a > save) && (*a!='.') && (*a!='/')) a--;
  970.     if (*a!='.') {   // agh pas de point
  971.       //strcatbuff(save,".none");                 // a Θviter
  972.       strcatbuff(save,".html");                   // prΘfΘrable!
  973.       if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  974.         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Default HTML type set for %s%s"LF,adr_complete,fil_complete);
  975.         test_flush;
  976.       }
  977.     }
  978.   }
  979.  
  980.   // effacer pass au besoin pour les autentifications
  981.   // (plus la peine : masquΘ au dΘbut)
  982. /*
  983.   {
  984.     char* a=jump_identification(save);
  985.     if (a!=save) {
  986.       char tempo[HTS_URLMAXSIZE*2];
  987.       char *b;
  988.       tempo[0]='\0';
  989.       strcpybuff(tempo,"[");
  990.       b=strchr(save,':');
  991.       if (!b) b=strchr(save,'@');
  992.       if (b)
  993.         strncatbuff(tempo,save,(int) b-(int) a);
  994.       strcatbuff(tempo,"]");
  995.       strcatbuff(tempo,a);
  996.       strcpybuff(save,a);
  997.     }
  998.   }
  999. */
  1000.  
  1001.   // Θviter les / au dΘbut (cause: N100)
  1002.   if (save[0]=='/') {
  1003.     char tempo[HTS_URLMAXSIZE*2];
  1004.     strcpybuff(tempo,save+1);
  1005.     strcpybuff(save,tempo);
  1006.   }
  1007.  
  1008.   // changer les ~,:,",*,? en _ pour sauver sur disque
  1009.   hts_replace(save,'~','_');  // interdit sous unix (~foo)
  1010.   //
  1011.   hts_replace(save,'\\','_');
  1012.   hts_replace(save,':','_');  // interdit sous windows
  1013.   hts_replace(save,'*','_');  // interdit sous windows
  1014.   hts_replace(save,'?','_');  // doit pas arriver!!
  1015.   hts_replace(save,'\"','_');  // interdit sous windows
  1016.   hts_replace(save,'<','_');  // interdit sous windows
  1017.   hts_replace(save,'>','_');  // interdit sous windows
  1018.   hts_replace(save,'|','_');  // interdit sous windows
  1019.   //
  1020.   hts_replace(save,'@','_');
  1021.   //
  1022.   { // Θliminer les // (comme ftp://)
  1023.     char* a;
  1024.     while( (a=strstr(save,"//")) ) *a='_';
  1025.     // Eliminer chars spΘciaux
  1026.     a=save -1 ;
  1027.     while(*(++a))
  1028.       if ( ((unsigned char)(*a) <= 31)
  1029.           || ((unsigned char)(*a) == 127) )
  1030.         *a='_';
  1031.   }
  1032.  
  1033.    
  1034. #if HTS_OVERRIDE_DOS_FOLDERS
  1035.   /* Replace /foo/nul/bar by /foo/nul-/bar */
  1036.   {
  1037.     int i=0;
  1038.     while(hts_tbdev[i][0]) {
  1039.       char* a=save;
  1040.       while((a=strstr(a,hts_tbdev[i]))) {
  1041.         switch ( (int) a[strlen(hts_tbdev[i])] ) {
  1042.         case '\0':
  1043.         case '/':  {
  1044.           char tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0';
  1045.           strncatbuff(tempo,save,(int) (a - save) + strlen(hts_tbdev[i]));
  1046.           strcatbuff(tempo,"-");
  1047.           strcatbuff(tempo,a+strlen(hts_tbdev[i]));
  1048.           strcpybuff(save,tempo);
  1049.                    }
  1050.           break;
  1051.         }
  1052.         a+=strlen(hts_tbdev[i]);
  1053.       }
  1054.       i++;
  1055.     }
  1056.   }
  1057. #endif
  1058.  
  1059.   // conversion 8-3 .. y compris pour les rΘpertoires
  1060.   if (opt->savename_83) {
  1061.     char n83[HTS_URLMAXSIZE*2];
  1062.     long_to_83(opt->savename_83,n83,save);
  1063.     strcpybuff(save,n83);
  1064.   }
  1065.  
  1066.  
  1067.   /* ensure that there is no ../ (potential vulnerability) */
  1068.   fil_simplifie(save);
  1069.  
  1070. #if HTS_ANALYSTE
  1071.   {
  1072.     hts_htmlcheck_savename(adr_complete,fil_complete,referer_adr,referer_fil,save);
  1073.     if ( (opt->debug>0) && (opt->log!=NULL) ) {
  1074.       fspc(opt->log,"info"); fprintf(opt->log,"engine: save-name: local name: %s%s -> %s"LF,adr,fil,save);
  1075.       test_flush;
  1076.     }
  1077.   }
  1078. #endif
  1079.  
  1080.   // chemin primaire Θventuel A METTRE AVANT
  1081.   if (strnotempty(opt->path_html)) {
  1082.     char tempo[HTS_URLMAXSIZE*2];
  1083.     strcpybuff(tempo,opt->path_html);
  1084.     strcatbuff(tempo,save);
  1085.     strcpybuff(save,tempo);
  1086.   }
  1087.  
  1088.  
  1089.   // vΘrifier que le nom n'est pas dΘja pris...
  1090.   if (liens!=NULL) { 
  1091.     int nom_ok;
  1092.     do {
  1093.       int i;
  1094.       int len;
  1095.       len=strlen(save);    // taille
  1096.       //
  1097.       nom_ok=1;  // α priori bon
  1098.       // on part de la fin pour optimiser, plus les opti de taille pour aller encore plus vite..
  1099. #if DEBUG_SAVENAME
  1100. printf("\nStart search\n");
  1101. #endif
  1102.  
  1103. #if HTS_HASH
  1104.       i=hash_read(hash,save,"",0);      // lecture type 0 (sav)
  1105.       if (i>=0)
  1106. #else
  1107.       for(i=lien_tot-1;i>=0;i--) {
  1108. #if DEBUG_SAVENAME
  1109. printf("%cParse: %d",13,i);
  1110. #endif
  1111.         
  1112.         if (liens[i]->sav_len==len) {    // mΩme taille de chaεne          
  1113. #if HTS_CASSE
  1114.           if (strcmp(liens[i]->sav,save)==0)    // existe dΘja
  1115. #else
  1116.           if (strfield2(liens[i]->sav,save))    // un tel nom existe dΘja
  1117. #endif
  1118. #endif
  1119.           {
  1120. #if HTS_CASSE
  1121.             if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  1122. #else
  1123.             if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  1124. #endif
  1125.             {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  1126.               //printf("Ok, %s\n",save);
  1127.               //i=lien_tot;    // sortir
  1128.               i=0;
  1129. #if DEBUG_SAVENAME
  1130. printf("\nOK ALREADY DEFINED\n",13,i);
  1131. #endif
  1132.             } else {  // utilisΘ par un AUTRE, changer de nom
  1133.               char tempo[HTS_URLMAXSIZE*2];
  1134.               char* a=save+strlen(save)-1;
  1135.               char* b;
  1136.               int n=2;       
  1137.               tempo[0]='\0';
  1138.  
  1139. #if DEBUG_SAVENAME
  1140. printf("\nWRONG CASE UNMATCH : \n%s\n%s, REDEFINE\n",liens[i]->fil,fil_complete);
  1141. #endif
  1142.               nom_ok=0;
  1143.               i=0;
  1144.               
  1145.               while(( a > save) && (*a!='.') && (*a!='\\') && (*a!='/')) a--;
  1146.               if (*a=='.')
  1147.                 strncatbuff(tempo,save,(int) (a - save));
  1148.               else
  1149.                 strcatbuff(tempo,save);
  1150.               
  1151.               // tester la prΘsence d'un -xx (ex: index-2.html -> index-3.html)
  1152.               b=tempo+strlen(tempo)-1;
  1153.               while (isdigit((unsigned char)*b)) b--;
  1154.               if (*b=='-') {
  1155.                 sscanf(b+1,"%d",&n);
  1156.                 *b='\0';    // couper
  1157.                 n++;  // plus un
  1158.               }
  1159.               
  1160.               // en plus il faut gΘrer le 8-3 .. pas facile le client
  1161.               if (opt->savename_83) {
  1162.                 int max;
  1163.                 char* a=tempo+strlen(tempo)-1;
  1164.                 while(( a > tempo) && (*a!='/')) a--;
  1165.                 if (*a=='/') a++;
  1166.                 max=max_char-1-nombre_digit(n);
  1167.                 if ((int) strlen(a)>max)
  1168.                   *(a+max)='\0';  // couper sinon il n'y aura pas la place!
  1169.               }
  1170.               
  1171.               // ajouter -xx (ex: index.html -> index-2.html)
  1172.               sprintf(tempo+strlen(tempo),"-%d",n);
  1173.               
  1174.               // ajouter extension
  1175.               if (*a=='.')
  1176.                 strcatbuff(tempo,a);
  1177.               
  1178.               strcpybuff(save,tempo);
  1179.               
  1180.               //printf("switched: %s\n",save);
  1181.               
  1182.             }  // if
  1183. #if HTS_HASH
  1184.           }
  1185. #else
  1186.           }  // if
  1187.         }  // if sav_len
  1188.       }  // for
  1189. #endif
  1190. #if DEBUG_SAVENAME
  1191. printf("\nEnd search, %s\n",fil_complete);
  1192. #endif
  1193.     } while(!nom_ok);
  1194.     
  1195.   }
  1196.   
  1197.   //printf("'%s' %s %s\n",save,adr,fil);
  1198.       
  1199.   return 0;
  1200. }
  1201.  
  1202. /* nom avec md5 urilisΘ partout */
  1203. void standard_name(char* b,char* dot_pos,char* nom_pos,char* fil_complete,int short_ver) {
  1204.   b[0]='\0';
  1205.   /* Nom */
  1206.   if (dot_pos) {
  1207.     if (!short_ver)    // Noms longs
  1208.       strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  1209.     else
  1210.       strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  1211.   } else {
  1212.     if (!short_ver)    // Noms longs
  1213.       strcatbuff(b,nom_pos);
  1214.     else
  1215.       strncatbuff(b,nom_pos,8);
  1216.   }
  1217.   /* MD5 - 16 bits */
  1218.   strncatbuff(b,url_md5(fil_complete),4);
  1219.   /* Ext */
  1220.   if (dot_pos) {
  1221.     strcatbuff(b,".");
  1222.     if (!short_ver)    // Noms longs
  1223.       strcatbuff(b,dot_pos+1);
  1224.     else
  1225.       strncatbuff(b,dot_pos+1,3);
  1226.   } else {
  1227.     if (!short_ver)    // Noms longs
  1228.       strcatbuff(b,DEFAULT_EXT);    // pas de..
  1229.     else
  1230.       strcatbuff(b,DEFAULT_EXT_SHORT);    // pas de..
  1231.   }
  1232. }
  1233.  
  1234.  
  1235. /* Petit md5 */
  1236. char* url_md5(char* fil_complete) {
  1237.   char* digest;
  1238.   char* a;
  1239.   NOSTATIC_RESERVE(digest, char, 32+2);
  1240.   digest[0]='\0';
  1241.   a=strchr(fil_complete,'?');
  1242.   if (a) {
  1243.     if (strlen(a)) {
  1244.       char buff[HTS_URLMAXSIZE*2];
  1245.       a++;
  1246.       digest[0]=buff[0]='\0';
  1247.       strcatbuff(buff,a);         /* query string MD5 */
  1248.       domd5mem(buff,strlen(buff),digest,1);
  1249.     }
  1250.   }
  1251.   return digest;
  1252. }
  1253.  
  1254. // interne α url_savename: ajoute une chaεne α une autre avec \ -> /
  1255. void url_savename_addstr(char* d,char* s) {
  1256.   int i=strlen(d);
  1257.   while(*s) {
  1258.     if (*s=='\\')  // remplacer \ par des /
  1259.       d[i++]='/';
  1260.     else
  1261.       d[i++]=*s;
  1262.     s++;
  1263.   }
  1264.   d[i]='\0';
  1265. }
  1266.  
  1267. #undef test_flush
  1268.